﻿#define IDE_DEBUG_

using Hydrogen.Cmd.Interfaces;
using Hydrogen.Console;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using SConsole = System.Console;

namespace Hydrogen.Cmd
{
    class Program
    {
        public static string currentDir;
        public static Dictionary<string, Type> commDic = new Dictionary<string, Type>();
        private static string cmdsDir = "cmds";

        /// <summary>
        /// 主函数
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
#if IDE_DEBUG
            string consoleCMD = @"ec -f gb2312 -t utf-8 -d E:\Studio\Unity\Custom3DGame\Excels\Localization\output -pattern *.loc";
            //string consoleCMD = "p2j -sp 2.png -q 50";
            args = consoleCMD.Split(' ');
#endif
            cmdsDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, cmdsDir);
            if (args.Length < 1)
            {
                ConsoleLog.LogWarning("Press h or help to get Help.");
                return;
            }
            Init();

            var cmdStr = args[0];
            var cmd = GetCommandInstance(cmdStr.ToLower());
            if (cmd == null)
            {
                ConsoleLog.LogError("The command [{0}] is not exist. Press lc or listcommand to get the list of command supported.", cmdStr);
            }
            else
            {
                try
                {
                    cmd.Invoke(args);
                }
                catch (Exception e)
                {
                    ConsoleLog.LogError(e.ToString());
                }
            }

#if IDE_DEBUG
            SConsole.WriteLine("Prass any key to exit.");
            SConsole.ReadKey();
#endif
        }

        private static void Init()
        {
            var buildinTypes = Assembly.GetAssembly(typeof(Program)).GetTypes();
            AddCmdTypes2Dic(buildinTypes);

            currentDir = Environment.CurrentDirectory;
            if (!Directory.Exists(cmdsDir))
            {
                Directory.CreateDirectory(cmdsDir);
                ConsoleLog.LogWarning("Have no Commands in {0}\n", Path.GetFullPath(cmdsDir));
                return;
            }
            else
            {
                var dlls = new List<string>();
                dlls.AddRange(Directory.GetFiles(cmdsDir, "*.dll"));
                foreach (var item in dlls)
                {
                    try
                    {
                        var assembly = Assembly.LoadFile(Path.GetFullPath(item));
                        var types = assembly.GetTypes();
                        AddCmdTypes2Dic(types);
                    }
                    catch (Exception e)
                    {
                        ConsoleLog.LogError(e.ToString());
                    }
                }
            }
        }

        private static void AddCmdTypes2Dic(Type[] types)
        {
            foreach (var t in types)
            {
                if (!typeof(CommandBase).IsAssignableFrom(t)) continue;
                var attr = t.GetCustomAttribute<CommandFlagAttribute>();
                if (attr == null) continue;
                foreach (var cmd in attr.Flags)
                {
                    if (commDic.ContainsKey(cmd.ToString())) continue;
                    commDic.Add(cmd.ToString(), t);
                }
            }
        }

        public static CommandBase GetCommandInstance(string cmdStr)
        {
            if (commDic.ContainsKey(cmdStr))
            {
                return GetCommandInstance(commDic[cmdStr]);
            }
            return null;
        }

        public static CommandBase GetCommandInstance<T>() where T : CommandBase, new()
        {
            return GetCommandInstance(typeof(T));
        }

        public static CommandBase GetCommandInstance(Type type)
        {
            return Activator.CreateInstance(type) as CommandBase;
        }

    }
}
